home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / elv18src.zip / vmswild.c < prev    next >
C/C++ Source or Header  |  1993-08-07  |  18KB  |  514 lines

  1. /*
  2.    This 'C' module may be included prior to the ``main'' programs on VMS in
  3.    order to allow 'C' arguments to contain redirection symbols (<,>,>>) and
  4.    VMS wild cards (*,% ...], [-).  By including this module, two programs
  5.    redirect() and expand() are run prior to turning control over to
  6.    your main() entry point.
  7.  
  8. /*
  9.     redirect-- Gregg Townsend circa 1983,
  10.     expand-- John Campbell circa 1987
  11.  
  12.    This code is public domain, others may use it freely. Credit, however, to
  13.    Gregg Townsend (who wrote ``redirect()'') and John Campbell (who followed
  14.    with ``expand()'') would be appreciated.  If someone writes the next
  15.    logical successor ``pipe()'', please email a copy to
  16.    ...!arizona!naucse!jdc (John Campbell) :-).
  17. */
  18.  
  19. #include <rms>   /* No easy way to tell if this has already been included. */
  20. #ifndef ERANGE   /* Include only if missing. */
  21. /* #include <stdlib>  causes lots of warnings. */
  22. #endif
  23. #include <stdio.h>  /* Stdio.h won't include itself twice. */
  24.  
  25. /* Expansion of wild cards is done using RMS. */
  26. typedef struct NAMBLK { struct NAM nam;         /* VMS nam block structure */
  27.                  char es[NAM$C_MAXRSS],         /* Extended string         */
  28.                       rs[NAM$C_MAXRSS];         /* Resultant string        */
  29.                };
  30.  
  31. #define ErrorExit 2
  32.  
  33. /* Allow the user to override _N_FARGS or _E_FLAG if they wish. */
  34. #ifndef _N_FARGS
  35. #define _N_FARGS 0
  36. #endif
  37. #ifndef _E_FLAG
  38. #define _E_FLAG 2
  39. #endif
  40. /*
  41.    Since the following will possibly be included in a single module, try
  42.    hard to avoid name conflicts. (Just being static doesn't cut it if
  43.    compiled in the same module.)
  44. */
  45. #define redirect     _r_edirect
  46. #define filearg      _f_ilearg
  47. #define expand       _e_xpand
  48. #define wild_found   _w_ild_found
  49. #define wild_expand  _w_ild_expand
  50.  
  51. main(argc, argv, envp)
  52. int argc;
  53. char *argv[], *envp[];
  54. {
  55.    char **expand();
  56.  
  57.    redirect (&argc, argv, _N_FARGS);
  58.    argv = expand (&argc, argv, _E_FLAG);
  59.  
  60. /* Make the user's main entry point this routine's entry point. */
  61. #define main _user_main
  62.    _user_main (argc, argv, envp);
  63. }
  64.  
  65. /*
  66.  * redirect(&argc,argv,nfargs) - redirect standard I/O
  67.  *    int *argc         number of command arguments (from call to main)
  68.  *    char *argv[]      command argument list (from call to main)
  69.  *    int nfargs        number of filename arguments to process
  70.  *
  71.  * argc and argv will be adjusted by redirect.
  72.  *
  73.  * redirect processes a program's command argument list and handles redirection
  74.  * of stdin, and stdout.  Any arguments which redirect I/O are removed from the
  75.  * argument list, and argc is adjusted accordingly.  redirect would typically be
  76.  * called as the first statement in the main program.
  77.  *
  78.  * Files are redirected based on syntax or position of command arguments.
  79.  * Arguments of the following forms always redirect a file:
  80.  *
  81.  *    <file     redirects standard input to read the given file
  82.  *    >file     redirects standard output to write to the given file
  83.  *    >>file    redirects standard output to append to the given file
  84.  *
  85.  * It is often useful to allow alternate input and output files as the
  86.  * first two command arguments without requiring the <file and >file
  87.  * syntax.  If the nfargs argument to redirect is 2 or more then the
  88.  * first two command arguments, if supplied, will be interpreted in this
  89.  * manner:  the first argument replaces stdin and the second stdout.
  90.  * A filename of "-" may be specified to occupy a position without
  91.  * performing any redirection.
  92.  *
  93.  * If nfargs is 1, only the first argument will be considered and will
  94.  * replace standard input if given.  Any arguments processed by setting
  95.  * nfargs > 0 will be removed from the argument list, and again argc will
  96.  * be adjusted.  Positional redirection follows syntax-specified
  97.  * redirection and therefore overrides it.
  98.  *
  99.  */
  100.  
  101.  
  102. redirect(argc,argv,nfargs)
  103. int *argc, nfargs;
  104. char *argv[];
  105. {
  106.    int i;
  107.  
  108.    i = 1;
  109.    while (i < *argc)  {         /* for every command argument... */
  110.       switch (argv[i][0])  {            /* check first character */
  111.          case '<':                      /* <file redirects stdin */
  112.             filearg(argc,argv,i,1,stdin,"r");
  113.             break;
  114.          case '>':                      /* >file or >>file redirects stdout */
  115.             if (argv[i][1] == '>')
  116.                filearg(argc,argv,i,2,stdout,"a");
  117.             else
  118.                filearg(argc,argv,i,1,stdout,"w");
  119.             break;
  120.          default:                       /* not recognized, go on to next arg */
  121.             i++;
  122.       }
  123.    }
  124.    if (nfargs >= 1 && *argc > 1)        /* if positional redirection & 1 arg */
  125.       filearg(argc,argv,1,0,stdin,"r"); /* then redirect stdin */
  126.    if (nfargs >= 2 && *argc > 1)        /* likewise for 2nd arg if wanted */
  127.       filearg(argc,argv,1,0,stdout,"w");/* redirect stdout */
  128. }
  129.  
  130.  
  131.  
  132. /* filearg(&argc,argv,n,i,fp,mode) - redirect and remove file argument
  133.  *    int *argc         number of command arguments (from call to main)
  134.  *    char *argv[]      command argument list (from call to main)
  135.  *    int n             argv entry to use as file name and then delete
  136.  *    int i             first character of file name to use (skip '<' etc.)
  137.  *    FILE *fp          file pointer for file to reopen (typically stdin etc.)
  138.  *    char mode[]       file access mode (see freopen spec)
  139.  */
  140.  
  141. filearg(argc,argv,n,i,fp,mode)
  142. int *argc, n, i;
  143. char *argv[], mode[];
  144. FILE *fp;
  145. {
  146.    if (strcmp(argv[n]+i,"-"))           /* alter file if arg not "-" */
  147.       fp = freopen(argv[n]+i,mode,fp);
  148.    if (fp == NULL)  {                   /* abort on error */
  149.       fprintf(stderr,"%%can't open %s",argv[n]+i);
  150.       exit(ErrorExit);
  151.    }
  152.    for ( ;  n < *argc;  n++)            /* move down following arguments */
  153.       argv[n] = argv[n+1];
  154.    *argc = *argc - 1;                   /* decrement argument count */
  155. }
  156.  
  157. /* EXPAND code. */
  158.  
  159. /* Global prototype. */
  160. char **expand (int *argc, const char *argv[], const int flag);
  161. /*-
  162.    ``expand()'' is a routine to expand wild-cards to file specifications.
  163.    This routine is often used in conjunction with ``redirect()'' to provide
  164.    both wild card expansion and standard file redirection prior to doing
  165.    any real work in a 'C' program.
  166.  
  167.    Normal usage is to include the following line prior to using argc or
  168.    argv in main():
  169.  
  170.      argv = expand (&argc, argv, 0);
  171.  
  172.    ``argc'' will be adjusted by ``expand()'', the return value from expand
  173.    will replace ``argv''.
  174.  
  175.    ``expand()'' processes a program's command argument list and expands any
  176.    wild cards into zero or more argv entries. Only arguments that posses VMS
  177.    wild-cards are expanded. Wild cards searched for are ``*'', ``%'',
  178.    ``...]'', and ``[-''. If the wild-card is found inside a single or double
  179.    quote ("*" or '%') then they are not counted as wild-cards. Be aware that
  180.    the expansion of a VMS wild card will match all VMS files, including
  181.    directory files (".DIR;1").
  182.  
  183.    NOTE: The use of quotes in VMS requires thinking about how the CLI expands
  184.    things before handing the argument line over to your program.  Do not
  185.    expect "*" to avoid expansion, use """*""" instead.  Likewise, expression
  186.    substitution precludes the use of (') to quote wild cards:
  187.            $ A := HELLO
  188.            $ ECHO 'a'   ! 'C' program that calls ``expand()''
  189.            hello
  190.    The easiest way to escape a wild-card may be "'*'".  The point is that
  191.    ``expand()'' will only recognize quotes passed into main().
  192.  
  193.    ``expand()'' references the VMS runtime routines, you will need to
  194.    link with the 'C' RTL whenever expand is used.
  195.  
  196.    Parameters:
  197.  
  198.          argc:  Pointer to the number of command arguments (from main),
  199.                 the contents of this parameter are modified.
  200.  
  201.          argv:  Pointer to the initial command argument list (from main),
  202.                 the contents are copied into a new array which is returned
  203.                 from this routine.
  204.  
  205.          flag:  Flag indicating how to expand wild-cards:
  206.                    0 - Complete file name expansion
  207.                    1 - only file name (no directory or version).
  208.                    2 - directory info and file name (no version).
  209.                    3 - file name an